#include "stdafx.h"
#include "profiler.h"
#include "specprivate.h"

namespace {
	const char PLUGIN[] = "plugin";
	const char PLUGIN_NAME[] = "name";
	const char PLUGIN_ENABLE[] = "enable";
}

static inline QString msgAttributeMissing(const char *elt, const char *attribute)
{
	return QCoreApplication::translate("PluginSpec", "'%1' misses attribute '%2'").arg(QLatin1String(elt), QLatin1String(attribute));
}

static inline QString msgInvalidFormat(const char *content)
{
	return QCoreApplication::translate("PluginSpec", "'%1' has invalid format").arg(QLatin1String(content));
}

Profiler::Profiler()
	: QObject(NULL)
	, errorString("")
	, hasError(false)
{

}

Profiler::~Profiler()
{
	RemoveAllSpec();
}

bool Profiler::read( const QString &fileName )
{
	RemoveAllSpec();

	QFile file(fileName);
	if (!file.open(QIODevice::ReadOnly))
		return reportError(tr("Cannot open file %1 for reading: %2")
		.arg(QDir::toNativeSeparators(file.fileName()), file.errorString()));

	QXmlStreamReader reader(&file);
	while (!reader.atEnd()) {
		reader.readNext();
		switch (reader.tokenType()) {
		case QXmlStreamReader::StartElement:
			readPluginSpec(reader);
			break;
		default:
			break;
		}
	}

	if (reader.hasError())
		return reportError(tr("Error parsing file %1: %2, at line %3, column %4")
		.arg(QDir::toNativeSeparators(file.fileName()))
		.arg(reader.errorString())
		.arg(reader.lineNumber())
		.arg(reader.columnNumber()));

	return true;
}

bool Profiler::reportError( const QString &err )
{
	errorString = err;
	hasError = true;
	return false;
}

void Profiler::readPluginSpec( QXmlStreamReader &reader )
{
	QString element = reader.name().toString();
	if (element != QLatin1String(PLUGIN)) {
		reader.raiseError(QCoreApplication::translate("PluginSpec", "Expected element '%1' as top level element")
			.arg(QLatin1String(PLUGIN)));
		return;
	}

	while (!reader.atEnd()) {
		reader.readNext();
		switch (reader.tokenType()) {
		case QXmlStreamReader::StartElement:
			{
				QString name = reader.attributes().value(QLatin1String(PLUGIN_NAME)).toString();
				if (name.isEmpty()) {
					reader.raiseError(msgAttributeMissing(PLUGIN, PLUGIN_NAME));
					return;
				}

				QVariant enable = reader.attributes().value(QLatin1String(PLUGIN_ENABLE)).toString();
				if (name.isEmpty()) {
					reader.raiseError(msgAttributeMissing(PLUGIN, PLUGIN_ENABLE));
					return;
				}

				QFileInfo fileInfo(name);
				if (fileInfo.exists())
				{
					SpecPrivate* p = new SpecPrivate;
					p->name = name;
					p->enable = enable.toBool();

					listSpec.append(p);
				}

				break;
			}
		default:
			break;
		}
	}
}

void Profiler::RemoveAllSpec()
{
	qDeleteAll(listSpec);
}

bool Profiler::save( const QString &fileName )
{
	QFile file(fileName);  
	if(file.open(QIODevice::WriteOnly | QIODevice::Text))
	{  
		QXmlStreamWriter writer(&file);  
		writer.setAutoFormatting(true);  
		writer.writeStartDocument();  
		writer.writeStartElement(PLUGIN);  

		foreach(SpecPrivate* p, listSpec)
		{ 
			writer.writeStartElement(PLUGIN);
			writer.writeAttribute(PLUGIN_NAME, p->name);  
			writer.writeAttribute(PLUGIN_ENABLE, QVariant(p->enable).toString());
			writer.writeEndElement();
		}

		writer.writeEndElement();  
		writer.writeEndDocument();  
		file.close();  

		return true;
	}  

	return false;
}

QList<SpecPrivate*>& Profiler::getSpec()
{
	return listSpec;
}

bool Profiler::add( SpecPrivate* spec )
{
	listSpec.append(spec);
	return true;
}

bool Profiler::isExist( const QString &fileName )
{
	foreach(SpecPrivate* p, listSpec)
	{
		if (p->name == fileName)
		{
			return true;
		}
	}

	return false;
}

QString Profiler::getProfilerFile()
{
	QDir dir(qApp->applicationDirPath());
	QString file = dir.filePath("plugin.xml");
	QFileInfo fileInfo(file);
	if (fileInfo.exists())
	{
		return file;
	}

	return QString("");
}